package team.southcat.wsyygh.hospital.service.impl;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.domain.Example;
import org.springframework.stereotype.Service;
import team.southcat.wsyygh.common.exception.WsyyghException;
import team.southcat.wsyygh.common.result.Result;
import team.southcat.wsyygh.common.result.ResultCodeEnum;
import team.southcat.wsyygh.hospital.service.DoctorService;
import team.southcat.wsyygh.model.pojo.hospital.Department;
import team.southcat.wsyygh.model.pojo.hospital.DepartmentVo;
import team.southcat.wsyygh.model.pojo.hospital.Doctor;
import team.southcat.wsyygh.hospital.mapper.DepartmentMapper;
import team.southcat.wsyygh.hospital.service.DepartmentService;
import team.southcat.wsyygh.model.pojo.hospital.Hospital;
import team.southcat.wsyygh.model.pojo.user.Admin;
import team.southcat.wsyygh.user.client.AdminFeignClient;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.stream.Collectors;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author QiuSiYi
 * @since 2023-04-20
 */
@Service
public class DepartmentServiceImpl extends ServiceImpl<DepartmentMapper, Department> implements DepartmentService {

    @Autowired
    private DoctorService doctorService;

    @Resource
    private DepartmentService departmentService;

    @Autowired
    private AdminFeignClient adminFeignClient;

    //分页查询科室列表
    @Override
    public Page getDepartmentPageList(Integer page, Integer pageSize, Department department, String adminId) {

        //分页构造器,传入页码和大小
        Page<Department> pageInfo = new Page<>(page, pageSize);
        //条件构造器
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();

        //只查询当前可以管理的医院
        Admin admin = getAdmin(adminId);
        queryWrapper.eq(Department::getHospitalId, admin.getHospitalId());

        //添加查询条件
        //父级科室
        queryWrapper.eq(department.getParentId() != null, Department::getParentId, department.getParentId());
        // 科室名称
        queryWrapper.like(department.getDepartmentName() != null, Department::getDepartmentName, department.getDepartmentName());
        //不查询父级科室，查子科室
        queryWrapper.ne(Department::getId, 1);

        //执行查询
        this.page(pageInfo, queryWrapper);

        //对象拷贝为Vo对象Page
        Page<DepartmentVo> voPage = new Page<>();
        BeanUtils.copyProperties(pageInfo, voPage);

        //取出数据并赋值转换
        List<Department> records = pageInfo.getRecords();

        //使用流转换
        List<DepartmentVo> departmentVos = records.stream().map((item) -> {
            DepartmentVo departmentVo = new DepartmentVo();
            BeanUtils.copyProperties(item, departmentVo);

            //根据父ID查询出父级数据
            Department parentDepartment = baseMapper.selectById(item.getParentId());
            if (parentDepartment != null){
                departmentVo.setParentName(parentDepartment.getDepartmentName());
            }

            return departmentVo;
        }).collect(Collectors.toList());

        //放数据，返回
        voPage.setRecords(departmentVos);
        return voPage;
    }

    private Admin getAdmin(String adminId) {
        Object adminObj = adminFeignClient.getAdminById(Integer.valueOf(adminId)).getData();
        return JSONObject.parseObject(JSON.toJSONString(adminObj), Admin.class);
    }

    //查询父级科室下的科室
    @Override
    @Cacheable("department_cache_p")
    public List<DepartmentVo> getByParentId(long parentId) {
        //条件构造器
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.ne(Department::getId,1);
        queryWrapper.eq(Department::getParentId, parentId);
        //queryWrapper.ne(Department::getId, 1);

        //执行,查询出所有父级科室
        List<Department> departments = baseMapper.selectList(queryWrapper);

        //遍历查询出所有父级科室下的科室
        List<DepartmentVo> departmentVos = departments.stream().map((item) -> {
            DepartmentVo departmentVo = new DepartmentVo();
            BeanUtils.copyProperties(item, departmentVo);

            LambdaQueryWrapper<Department> queryWrapper1 = new LambdaQueryWrapper<>();
            queryWrapper1.eq(Department::getParentId, item.getId());
            List<Department> departments1 = baseMapper.selectList(queryWrapper1);

            List<DepartmentVo> collect = departments1.stream().map((item1) -> {
                DepartmentVo departmentVo2 = new DepartmentVo();
                BeanUtils.copyProperties(item1, departmentVo2);

                return departmentVo2;
            }).collect(Collectors.toList());

            departmentVo.setChildren(collect);
            return departmentVo;
        }).collect(Collectors.toList());

        return departmentVos;
    }

    //添加科室
    @Override
    public Result addDepartment(Department department, String adminId) {
        //判断名称是否重复
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(department != null, Department::getDepartmentName, department.getDepartmentName());
        Admin admin = getAdmin(adminId);
        queryWrapper.eq(Department::getHospitalId, admin.getHospitalId());

        //查询
        Department has = baseMapper.selectOne(queryWrapper);
        if (has != null){
            //存在
            return Result.fail().message("该科室名称已经存在，请重新输入");
        }

        //不存在，保存
        department.setHospitalId(admin.getHospitalId());
        int insert = baseMapper.insert(department);
        return insert == 1 ? Result.ok() : Result.fail().message("保存失败！");
    }

    //删除科室
    @Override
    public Result deleteById(long id) {
        //1.不删除父级科室
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper();
        queryWrapper.eq(Department::getParentId, id);
        List<Department> departments = baseMapper.selectList(queryWrapper);
        if (departments.size() != 0){
            return Result.fail().message("该科室下有子科室，无法删除");
        }

        // 2.科室有医生不删除
        LambdaQueryWrapper<Doctor> doctorLambdaQueryWrapper = new LambdaQueryWrapper<>();
        doctorLambdaQueryWrapper.eq(Doctor::getDepartmentId, id);
        List<Doctor> doctors = doctorService.getBaseMapper().selectList(doctorLambdaQueryWrapper);
        if (doctors.size() != 0){
            return Result.fail().message("该科室下存在医生信息，无法删除");
        }

        int i = baseMapper.deleteById(id);
        return i != 0 ? Result.ok() : Result.fail().message("删除失败");
    }

    @Override
    public List<Department> getByName(List<String> departmentName) {
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.like(Department::getDepartmentName, departmentName);
        List<Department> departments = departmentService.list(queryWrapper);
        return departments;
    }

    @Override
    @Cacheable("department_cache_h")
    public List<DepartmentVo> getByHospitalId(int id) {

        //查询全部科室所在id
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Department::getHospitalId, id);
        queryWrapper.eq(Department::getDepartmentName, "全部科室");
        Department allDepartment = baseMapper.selectOne(queryWrapper);
        if (allDepartment == null){
            return null;
        }

        //查询该医院的所有父级科室
        queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Department::getParentId, allDepartment.getId());
        List<Department> parentList = baseMapper.selectList(queryWrapper);

        //遍历
        List<DepartmentVo> result = parentList.stream().map(department -> {
            return switchVO(department);
        }).collect(Collectors.toList());

        return result;
    }

    private DepartmentVo switchVO(Department department) {
        DepartmentVo res = new DepartmentVo();
        BeanUtils.copyProperties(department, res);

        //查询子科室
        LambdaQueryWrapper<Department> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(Department::getParentId, department.getId());
        List<Department> childList = baseMapper.selectList(wrapper);
        List<DepartmentVo> childVoList = new ArrayList<>();
        //封装小科室
        for (Department child : childList) {
            DepartmentVo departmentVo = new DepartmentVo();
            BeanUtils.copyProperties(child, departmentVo);
            childVoList.add(departmentVo);
        }

        res.setChildren(childVoList);
        return res;
    }

    @Override
    public List<DepartmentVo> getAllByAdminId(String adminId) {
        //获取医院id
        Admin admin = getAdmin(adminId);
        //查到“全部科室”的id然后查询
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Department::getDepartmentName, "全部科室");
        queryWrapper.eq(Department::getHospitalId, admin.getHospitalId());

        Department department = baseMapper.selectOne(queryWrapper);
        List<DepartmentVo> list = new ArrayList<>();
        list.add(switchVO(department));
        list.addAll(this.getByParentId(department.getId()));

        return list;
    }

    @Override
    public boolean deleteByIds(List<Integer> ids) {
        boolean flag = true;
        //判断其中是否有父级科室
        LambdaQueryWrapper<Department> queryWrapper = new LambdaQueryWrapper<>();
        for (Integer id : ids) {
            queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(Department::getParentId, id);

            List<Department> departments = baseMapper.selectList(queryWrapper);
            if (departments.size() != 0){
                //含有子科室
                flag = false;
                break;
            }
        }

        if (flag){
            //没有父科室
            for (Integer id : ids) {
                this.deleteById(id);
            }
        }

        return flag;
    }

}
